package com.rd.sys.common.web.right;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import baseproj.common.right.IRightHandler;

import com.rd.sys.common.web.session.SessionUtil;
import com.rd.sys.dto.sys.operator.PrivOperationDto;

/**
 * 权限处理类.
 */
public class RightHandler implements IRightHandler {

    /** Action对应的后缀. */
    public static final String ACTION_SYMBOL = ".action";

    /** The instance. */
    private static RightHandler instance = null;

    /**
     * 私有构造函数.
     */
    private RightHandler() {

    }

    /**
     * Gets the single instance of RightHandler.
     * 
     * @return single instance of RightHandler
     */
    public static RightHandler getInstance() {
        if (instance != null) {
            return instance;
        } else {
            synchronized (RightHandler.class) {
                if (instance == null) {
                    instance = new RightHandler();
                }
            }
            return instance;
        }
    }

    /**
     * 判断某个操作是否有权限.
     * 
     * @param request
     *            http请求
     * @param operUrl
     *            操作权限
     * @return 当有权限时返回true,否则返回false
     * @throws Exception
     *             the exception
     */
    @SuppressWarnings("unchecked")
    @Override
    public boolean isPrivilege(ServletRequest request, String operUrl) throws Exception {
        HttpSession session = SessionUtil.getSession((HttpServletRequest) request);

        operUrl = operUrl.replaceAll(ACTION_SYMBOL, "");
        HashSet<String> privUrls = (HashSet<String>) session.getAttribute("operPrivs");

        if (privUrls == null) { // Session中权限列表为空,直接返回false
            return false;
        }
        if (privUrls.contains(operUrl)) { // Session中权限列表含有本操作
            return true;
        }
        if (privUrls.contains(operUrl.substring(0, operUrl.indexOf("_") + 1) + "*")) {
            // 若Session中权限列表包括本操作所属Action的全部方法,则也允许访问
            return true;
        }

        return false;
    }

    /**
     * 在缓存（Session）中增加操作员对应的权限.
     * 
     * @param request
     *            http请求
     * @param privUrlList
     *            操作员对应的所有权限列表
     * @throws Exception
     *             the exception
     * @version
     */
    public void addOperPrivs(ServletRequest request, List<PrivOperationDto> privUrlList) throws Exception {
        HttpSession session = SessionUtil.getSession((HttpServletRequest) request);

        // 脚本中的规则是: 逗号","分割不同的Action的操作,竖线"|"分割同一Action的不同操作
        // 如：action1_*,action2_add|edit

        if (privUrlList != null && privUrlList.size() > 0) {
            HashSet<String> privUrls = new HashSet<String>();

            Iterator<PrivOperationDto> it = privUrlList.iterator();
            PrivOperationDto privOperDto = null;
            // 1)遍历每一个操作权限
            while (it.hasNext()) {
                privOperDto = it.next();
                // 2)根据逗号分割出不同的Action操作
                String[] urls = privOperDto.getUrl().split("\\,");
                for (int i = 0; i < urls.length; i++) {
                    String url = urls[i];
                    // 3)如果同一Action操作中,没有再分不同的方法,则直接添加
                    if (url.indexOf("|") == -1) {
                        privUrls.add(url);
                    } else {// 4)若同一Action操作中存在不同方法,则根据竖线分割
                        String[] sub_urls = url.split("\\|");
                        String prix = sub_urls[0].substring(0, sub_urls[0].indexOf("_") + 1); // 取出Action前缀,下划线_是与Struts配置文件中相一致的

                        privUrls.add(sub_urls[0]); // 第0个直接添加
                        for (int j = 1; j < sub_urls.length; j++) {
                            privUrls.add(prix + sub_urls[j]); // 之后循环各个方法，将Action前缀和方法名组合后添加
                        }
                    }
                }
            }

            session.setAttribute("operPrivs", privUrls);
        }
    }

}
